package zack.project.domain.strategy.service.rule.tree.impl;

import zack.project.domain.strategy.adapter.repository.IStrategyRepository;
import zack.project.domain.strategy.model.valobj.RuleLogicCheckTypeVO;
import zack.project.domain.strategy.model.valobj.StrategyAwardStockKeyVO;
import zack.project.domain.strategy.service.armory.IStrategyDispatch;
import zack.project.domain.strategy.service.rule.tree.ILogicTreeNode;
import zack.project.domain.strategy.service.rule.tree.factory.DefaultTreeFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;

/**抽奖库存规则节点
 * @author A1793
 */
@Component("rule_stock")
@Slf4j
public class RuleStockLogicTreeNode implements ILogicTreeNode {

    @Resource
    IStrategyRepository strategyRepository;
    @Resource
    IStrategyDispatch strategyDispatch;

    /**
     * 在redis中扣减缓存库存后加库存余量锁,并通过redis的延迟队列更新数据库表{strategy_award}
     * @param userId
     * @param strategyId
     * @param awardId
     * @param ruleValue
     * @param endDateTime
     * @return
     */
    @Override
    public DefaultTreeFactory.TreeActionEntity logic(String userId,
                                                     Long strategyId,
                                                     Integer awardId,
                                                     String ruleValue,
                                                     Date endDateTime) {
        log.info("规则过滤-库存扣减 userId:{} strategyId:{} awardId:{}", userId, strategyId, awardId);
        //1.尝试在redis中扣减库存:先根据cacheKey("strategy_award_count_key_#{strategyId}_#{awardId}"),redisService.decr(cacheKey)
        //并根据返回的库存余量(surplus)来新设置一个("strategy_award_count_key_#{strategyId}_#{awardId}_#{surplus}")的锁
        boolean locked = strategyDispatch.subtractionAwardStock(strategyId, awardId,endDateTime);

        if(locked) {
            log.info("规则过滤-库存扣减-成功 userId:{} strategyId:{} awardId:{}", userId, strategyId, awardId);

            //向redis中名为("strategy_award_count_query_key")的延迟队列中放一条信息(StrategyAwardStockKeyVO)，
            // 在定时任务UpdateAwardStockJob中根据StrategyAwardStockKeyVO来更新库表{strategy_award}中的缓存
            strategyRepository.awardStockConsumeSendQueue(StrategyAwardStockKeyVO
                    .builder()
                    .awardId(awardId)
                    .strategyId(strategyId).build());

            return DefaultTreeFactory.TreeActionEntity.builder()
                    .ruleLogicCheckType(RuleLogicCheckTypeVO.TAKE_OVER)
                    .strategyAwardVO(DefaultTreeFactory.StrategyAwardVO.builder()
                            .awardRuleValue(ruleValue)
                            .awardId(awardId)
                            .build())
                    .build();
        }
        log.warn("规则过滤-库存扣减-告警，库存不足。userId:{} strategyId:{} awardId:{}", userId, strategyId, awardId);

        return DefaultTreeFactory.TreeActionEntity.builder()
                .ruleLogicCheckType(RuleLogicCheckTypeVO.ALLOW)
                .build();
    }
}
